﻿using FluentValidation;
using Nop.Core.Domain.Common;
using Nop.Services.Localization;
using Nop.Services.Logistics;
using Spotshub.Api.Models;

namespace Spotshub.Api.Validators
{
    public class AddressValidator : AbstractValidator<AddressModel>
    {
        public AddressValidator(ILocalizationService localizationService, ILogisticsService logisticsService)
        {
            const string phoneRegex = @"^[\\(]{0,1}([0-9]){3}[\\)]{0,1}[{ ,\-,.}]?([^0-1]){1}([0-9]){2}[{ ,\-,.}]?([0-9]){4}[ ]*((x|X){0,1}([0-9]){1,5}){0,1}$";
            RuleFor(x => x.FirstName)
                .NotEmpty()
                .Unless(x => x.AllowEmpty)
                .WithMessage(localizationService.GetResource("Address.Fields.FirstName.Required"));
            RuleFor(x => x.LastName)
                .NotEmpty()
                .Unless(x => x.AllowEmpty)
                .WithMessage(localizationService.GetResource("Address.Fields.LastName.Required"));
            RuleFor(x => x.Email)
               .NotEmpty()
               .Unless(x => x.AllowEmpty || x.AllowEmailEmpty)
               .WithMessage(localizationService.GetResource("Address.Fields.Email.Required"));

            RuleFor(x => x.Email)
                .EmailAddress()
                .Unless(x => (x.AllowEmpty || x.AllowEmailEmpty) && string.IsNullOrEmpty(x.Email))
                .WithMessage(localizationService.GetResource("Common.WrongEmail"));

            RuleFor(x => x.CountryId)
                .NotNull()
                .Unless(x => x.AllowEmpty)
                .WithMessage(localizationService.GetResource("Address.Fields.Country.Required"));
            RuleFor(x => x.CountryId)
                .NotEqual(0)
                .Unless(x => x.AllowEmpty)
                .WithMessage(localizationService.GetResource("Address.Fields.Country.Required"));

            RuleFor(x => x.StateProvinceId)
                .NotNull()
                .NotEqual(0)
                .Unless(x => x.AllowEmpty)
                .WithMessage(localizationService.GetResource("Address.Fields.StateProvince.Required"));


            //RuleFor(x => x.Company).NotEmpty().Unless(x => x.AllowEmpty).WithMessage(localizationService.GetResource("Account.Fields.Company.Required"));

            RuleFor(x => x.Address1).NotEmpty().Unless(x => x.AllowEmpty).WithMessage(localizationService.GetResource("Account.Fields.StreetAddress.Required"));

            RuleFor(x => x.ZipPostalCode).NotEmpty().Unless(x => x.AllowEmpty).WithMessage(localizationService.GetResource("Account.Fields.ZipPostalCode.Required"));

            RuleFor(x => x.ZipPostalCode)
                .Cascade(FluentValidation.CascadeMode.StopOnFirstFailure)
                .Matches(@"^ *[ABCEGHJKLMNPRSTVXYabceghjklmnprstvxy]{1}\d{1}[A-Za-z]{1} *\d{1}[A-Za-z]{1}\d{1} *$")
                .Unless(x => x.AllowEmpty || (x.Address1 != null && x.Address1.Contains("10 Glenlake Parkway"))) // Hard-coded backdoor for testing.
                .WithMessage(localizationService.GetResource("Address.Fields.Zippostalcode.Invalid"))
                .Must(zp => (logisticsService.GetDistrictByZipPostalCode(zp) != null))
                .Unless(x => x.AllowEmpty)
                .WithMessage(localizationService.GetResource("Address.Fields.Zippostalcode.NoService"))
                .Must((x, zp) =>
                    (!x.StateProvinceId.HasValue ||
                    x.StateProvinceId.Value == 0 ||
                    x.StateProvinceId.Value == logisticsService.GetDistrictByZipPostalCode(zp).StateProvinceId))
                .Unless(x => x.AllowEmpty)
                .WithMessage(localizationService.GetResource("Address.Fields.Zippostalcode.NotInStateProvince"));

            RuleFor(x => x.City).NotEmpty().Unless(x => x.AllowEmpty).WithMessage(localizationService.GetResource("Address.Fields.City.Required"));

            RuleFor(x => x.PhoneNumber).NotEmpty().Unless(x => x.AllowEmpty).WithMessage(localizationService.GetResource("Address.Fields.Phone.Required"));

            RuleFor(x => x.PhoneNumber)
                .Matches(phoneRegex)
                .When(x => !string.IsNullOrEmpty(x.PhoneNumber))
                .Unless(x => x.AllowEmpty)
                .WithMessage(localizationService.GetResource("Address.Fields.Phone.Invalid"));


            //RuleFor(x => x.CellPhoneNumber).NotEmpty().Unless(x => x.AllowEmpty).WithMessage(localizationService.GetResource("Address.Fields.Cellphonenumber.Required"));

            //RuleFor(x => x.CellPhoneNumber)
            //    .Matches(phoneRegex)
            //    .Unless(x => x.AllowEmpty)
            //    .WithMessage(localizationService.GetResource("Address.Fields.Cellphonenumber.Invalid"));


            RuleFor(x => x.Type)
                .NotNull()
                .NotEqual(AddressType.Unknown)
                .When(x => x.IsTypeRequired && !x.AllowEmpty)
                .WithMessage(localizationService.GetResource("logistics.order.fields.address.type.required"));
        }
    }
}